package Xmlcompare;


import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Date;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;


public class XMLValueComp
{
 private File xfile1;
 private File xfile2;
 
 private SimpleMap f1v;
 private SimpleMap f2v;
 public PrintWriter log;
 public static String[] ExclusionNode;
 public static int exl=0; 
 public static int Filefound=0;
 
 
 public static void Comparexml(String file1,String file2)
 {
	 Filefound=0;
  if (file2.equals(null)||file1.equals(null))
   printHelp();
  
  XMLValueComp xmlComp = new XMLValueComp(file1, file2);
  try
  {
	  ExclusionNode=BXmlCompare.ExcludeNode.split(",");  
  }
  catch (NullPointerException n) {
	exl=1;
}
  
  xmlComp.compare();
 }
 
 public static void printHelp()
 {
  System.out.println("Usage: xmlcomp file1 file2");
  System.exit(0);
 }
 public XMLValueComp(String file1, String file2)
 {
	 log=BXmlCompare.log;
  f1v = new SimpleMap();
  f2v = new SimpleMap();
  File f1 = new File(file1);
  File f2 = new File(file2);
  log.println("Verifying file : "+f1.getName());
  
  if (!f1.exists() || !f2.exists())
  {
	  
   
   Filefound=1;
   //System.exit(0);
  }
  xfile1 = f1;
  xfile2 = f2;
 }
 public void compare()
 {
	 if(Filefound==0)
	 {
	 
	 
  Document doc1 = Utils.stringToDocument(
      Utils.readStringFromFile(xfile1));
     Document doc2 = Utils.stringToDocument(
    Utils.readStringFromFile(xfile2));
  int err=0;
  if (doc1 == null || doc2 == null)
  {
   System.err.println("Could not build docs");
   //System.exit(0);
  }
  
  buildMap(f1v, doc1);
  buildMap(f2v, doc2);


  ArrayList<String> ETLArrary = new ArrayList<String>();
  ArrayList<String> ExpectedArray = new ArrayList<String>();

  ETLArrary.addAll(f1v.getCompleteItemList());
  ExpectedArray.addAll(f2v.getCompleteItemList());
  
  /*for(String etlTemp :ETLArrary)
  {
	  System.out.println("Etl :"+etlTemp);
	  
  }
  for(String Exptemp : ExpectedArray)
  {
	  System.out.println("Exp :"+Exptemp);
	   
  }*/
  //System.out.println(uniques.size());
  f2v.getCompleteItemList().size();
  for(String etlTemp : f2v.getCompleteItemList())
  {
	  //System.out.println("Etl2 :"+etlTemp);
	  ETLArrary.remove(etlTemp); 
  }
  
  
 
  
  for(String Exptemp : f1v.getCompleteItemList())
  {
	  //System.out.println("Exp2 :"+Exptemp);
	  ExpectedArray.remove(Exptemp); 
  }
  
	 
  
  
 
  
  int f2=1,f1=1;;
  ArrayList<String> actualremove = new ArrayList<String>();
  ArrayList<String> expectedremove = new ArrayList<String>();
  ArrayList<Integer> expectedindex = new ArrayList<Integer>();
  // System.out.println(uniques.size());
  //System.out.println(uniques1.size());
	  for(String file1value :ETLArrary)
	  { 
	  
		  
		  String spliff1[]=file1value.split("--"); int in=0;
		  for(String Expectedvalue :ExpectedArray)
		  {
			  
			  String spliff2[]=Expectedvalue.split("--");
			  if(spliff1[0].equals(spliff2[0]))
			  {
				  String []sp1= spliff1[1].split(" :: ");
				  String []sp2= spliff2[1].split(" :: ");
				  if(sp1[1].equals(sp2[1]))
				  {
					  if(!expectedindex.contains(new Integer(in)))
					  {
					  expectedindex.add(new Integer(in++));
					  actualremove.add(file1value);
					  expectedremove.add(Expectedvalue);
					  f1=0;
					  }
				  }
				  else
				  {
				  
				  if(!expectedindex.contains(new Integer(in)))
				  {
					  System.out.println("\tMismatching Values :"+f2+"\n\t\tExpected Value :\n\t\t\t"+Expectedvalue+"\n\tActual Value :\n\t\t\t"+file1value);
					  log.println("\tMismatching Values :"+f2+"\n\t\tExpected Value :\n\t\t\t"+Expectedvalue+"\n\t\tActual Value :\n\t\t\t"+file1value);
					  log.println();
				  expectedindex.add(new Integer(in++));
				  actualremove.add(file1value);
				  expectedremove.add(Expectedvalue);f1=0;
				  }
				 f2++;err++;
				  //break;
				  }
			  }in++;
			  if(f1==0)
			  {
				  continue;
			  }
			  
		  }//temp.remove(file1value);
		  
	  }
	  for(String uni : actualremove)
	  {
		  ETLArrary.remove(uni);
		 // System.out.println("Etl :"+uni);
	  }
		  
	  for(String uni : expectedremove)
	  {
		  ExpectedArray.remove(uni);  
		  //System.out.println("exp :"+uni);
	  }
		 
	 // System.out.println(uniques.size());
	  //System.out.println(uniques1.size());
	  if(ExpectedArray.size()!=0)
	  {
		  err++;
		  System.out.println("\tElements Missing in Actual Output file");
		  log.println("\tElements Missing in Actual Output file");
		  
		  for (String v : ExpectedArray)
		  { System.out.println(v);
		  log.println("\t"+v);
		  }
		  log.println();
	  }

	

	  if(ETLArrary.size()!=0)
	  {
		  err++;
		  System.out.println("\tExtra elements in Actual Output file");
		  log.println("\tExtra elements in Actual Output file");
		  for (String v : ETLArrary)
		  {
			  System.out.println(v);
			  log.println("\t"+v);
		  }
		  log.println();
		   
	  }
	  
  
  if(err==0)
  {
	  System.out.println("Actual and Expected File - Matching"); 
	  log.println("\tActual and Expected File - Matching");
  }
  log.println("-------------------------------------------------------------------------------------------------");
  
  
 }
	 else{
		 System.out.println("One of the files does not exist!");
		 
		  log.println("\tOne of the files does not exist!");
	 }
 }
 private void buildMap(SimpleMap map, Document doc)
 {
  Element e = doc.getDocumentElement();

if(exl==1)
{
	mapNodes1(map, e, "/" + e.getNodeName());
}
else
{
	mapNodes(map, e, "/" + e.getNodeName());
}
  
 }

//with Exclusion of Nodes
 private void mapNodes(SimpleMap map, Element elem, String parent)
 {
  for (int x = 0; x < elem.getChildNodes().getLength(); x++)
  {
   Node n = elem.getChildNodes().item(x);
   String path = "";
     
   if (n.getChildNodes().getLength() == 1)
   {
	  // path = parent + "/" + n.getNodeName();
	   
	  // System.out.println(path+"="+n.getTextContent());
	   
	   String path1="",currentnodename=n.getNodeName();
	  //System.out.println(n.getNodeName());
	   for(int i=0,j=0;i<n.getParentNode().getChildNodes().getLength();i++)
	   {
		  Node m= n.getParentNode().getChildNodes().item(i);
		  if(m.getNodeType() == Node.ELEMENT_NODE && m.getChildNodes().getLength()==1 )
		  { j++;
		  
			  if(j>1)
			  {int e=0;
				  for(String Exnode:ExclusionNode)
				  {
					  if(Exnode.equals(m.getNodeName()))
					  {
						  path1+="";
						  break;
					  }
					 
					  e++;
				  }
				  if(e>=ExclusionNode.length)
				  {
					  path1+= "and ['" + m.getNodeName()+"="+ m.getTextContent()+"']";
				  }
				    
			  }
			  else
			  {int e1=0;
				  for(String Exnode:ExclusionNode)
				  {
					  if(Exnode.equals(m.getNodeName()))
					  {
						  path1+=""; 
						  break;
					  }
					  
					  e1++;
				  }
				  if(e1>=ExclusionNode.length)
				  {
					  path1+= "['" + m.getNodeName()+"="+ m.getTextContent()+"']";
				  }
				    
			  }
			 
		  }
		 
	   }
	  // System.out.println(path1);
	   //path = parent +"['"+n.getNodeName()+"="+ n.getTextContent()+"']/" + n.getNodeName();
	   int e2=0;
	   for(String Exnode:ExclusionNode)
		  {
			  if(Exnode.equals(n.getNodeName()))
			  {
				  path1+=""; 
				  break;
			  }
			  
			  e2++;
		  }
		  if(e2>=ExclusionNode.length)
		  {
			  path = parent +"/" + n.getNodeName()+"--"+path1;
			   map.put(path, n.getTextContent());
		  }
	   //path = parent +"/" + n.getNodeName()+"--"+path1;
	   //map.put(path, n.getTextContent());
	   //System.out.println(path);
	   
   }
   else
   {
	    path = parent + "/" + n.getNodeName(); 
   }
    
   
  
	  
   
   if (n.getNodeType() == Node.ELEMENT_NODE)
   	{
	   mapNodes(map, (Element) n, path);
	}
   
  }
 }
 
 //without Exclusion
 private void mapNodes1(SimpleMap map, Element elem, String parent)
 {
  for (int x = 0; x < elem.getChildNodes().getLength(); x++)
  {
   Node n = elem.getChildNodes().item(x);
   String path;
     
   if (n.getChildNodes().getLength() == 1)
   {
	  // path = parent + "/" + n.getNodeName();
	   
	  // System.out.println(path+"="+n.getTextContent());
	   
	   String path1="",currentnodename=n.getNodeName();
	  //System.out.println(n.getNodeName());
	   for(int i=0,j=0;i<n.getParentNode().getChildNodes().getLength();i++)
	   {
		  Node m= n.getParentNode().getChildNodes().item(i);
		  if(m.getNodeType() == Node.ELEMENT_NODE && m.getChildNodes().getLength()==1 )
		  { j++;
			  if(j>1)
			  {
				  path1+= "and ['" + m.getNodeName()+"="+ m.getTextContent()+"']";  
			  }
			  else
			  {
				  path1+= "['" + m.getNodeName()+"="+ m.getTextContent()+"']";  
			  }
			 
		  }
		 
	   }
	  // System.out.println(path1);
	   //path = parent +"['"+n.getNodeName()+"="+ n.getTextContent()+"']/" + n.getNodeName();
	   path = parent +"/" + n.getNodeName()+"--"+path1;
	   map.put(path, n.getTextContent());
	   //System.out.println(path);
	   
   }
   else
   {
	    path = parent + "/" + n.getNodeName(); 
   }
    
   
  
	  
   
   if (n.getNodeType() == Node.ELEMENT_NODE)
   	{
	   mapNodes1(map, (Element) n, path);
	}
   
  }
 }
}
 
 
 